home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 3
/
BBS in a box - Trilogy III.iso
/
Files
/
System7 tools
/
U-Z
/
Zing
/
Source
/
main.c
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1992-06-23
|
20.9 KB
|
1,075 lines
|
[
TEXT/KAHL
]
// Main.c
// Ping 1.2
//
// A neat hack © 1992 Jon Wätte (h+@nada.kth.se)
//
// Freeware - permission granted to study & distribute free of charge,
// however, you may not sell this source or any derivate thereof, nor
// may you distribute modified source or a derivate thereof.
//
// Things to add may be:
// - Select & copy text from window
// - Undo
// - Sound sending/receiving
// - Save conversation
// - Backlog ?
// - Picture send/receive (separate window ?)
// - Drawing grow box
//
#include <EPPC.h>
#include <AppleEvents.h>
#include "Util.h"
#define STRING_SIZE 100
#define DELAY 40
#define STACK 5000
#define NAME_SIZE 33
#define MIN_WID_PIXELS 200
#define MAX_WID_PIXELS 700
#define RIGHT_STRIP 48
#define pingClass 'Ping'
#define pingPing 'Ping'
#define pingMessage 'Mesg'
#define pingSenderName 'Name'
#define pingSenderText 'Text'
#define pingSenderSound 'Snd '
#define pingSenderPict 'Pict'
#define pingSenderMisc 'Misc'
#define pingSenderTime 'Time'
short topPart = 220 ;
short bottomPart = 19 ;
short lineWidth = 232 ;
short lineHeight = 0 ;
short leftMarg = 4 ;
short topMarg = 0 ;
EventRecord gEvent ;
WindowPtr gWindow = NULL ;
int numLines = 0 ;
unsigned char * * theLines = NULL ;
FontInfo txInfo ;
Boolean gRunning = 1 ;
Rect textRect ;
TEHandle teH = NULL ;
LocationNameRec theLocation ;
Boolean hasDest = 0 ;
PortInfoRec thePPCPort ;
Str32 theNBPType ;
Boolean isIn = 1 ;
RgnHandle aRgn = NULL ;
NMRec gNmRec ;
unsigned char userName [ NAME_SIZE ] ;
long lastTime = 0 ;
// Standard toolbox initialization
//
static void
InitMac ( void )
{
InitGraf ( & qd . thePort ) ;
InitFonts ( ) ;
InitWindows ( ) ;
InitMenus ( ) ;
TEInit ( ) ;
InitDialogs ( NULL ) ;
// Initializing the PPC toolbox is not strictly necessary, but nice...
PPCInit ( ) ;
// We only need a few Ks of stack since we don't use recursion or stack-based calls
SetApplLimit ( CurStackBase - STACK ) ;
// Make sure we have our heap
MaxApplZone ( ) ;
// And maybe we need another master pointer block
MoreMasters ( ) ;
}
// Install a notification with sound, icon and diamond
//
static void
Notification ( void )
{
// Only while we're in the background...
if ( ! isIn ) {
// Is it already allocated ?
if ( ! gNmRec . nmIcon ) {
Clear ( gNmRec ) ;
gNmRec . qType = nmType ;
gNmRec . nmMark = 1 ;
gNmRec . nmIcon = GetResource ( 'SICN' , 128 ) ;
gNmRec . nmSound = ( Handle ) -1 ;
gNmRec . nmStr = NULL ;
gNmRec . nmResp = NULL ;
gNmRec . nmRefCon = 0L ;
NMInstall ( & gNmRec ) ;
}
}
}
// Add a string to the window. We use a cyclic buffer of pointers.
//
static void
AddString ( unsigned char * str , short len , unsigned char * user )
{
short ix ;
unsigned char * msg ;
Rect rect ;
// Check that we do not overwrite our buffers
if ( len > STRING_SIZE - 1 ) {
len = STRING_SIZE - 1 ;
}
SetRect ( & rect , 0 , 0 , lineWidth + leftMarg * 2 , topPart ) ;
SetEmptyRgn ( aRgn ) ;
ScrollRect ( & rect , 0 , - lineHeight , aRgn ) ;
EraseRgn ( aRgn ) ;
if ( len ) {
BlockMove ( str , & theLines [ 0 ] [ 1 ] , len ) ;
}
theLines [ 0 ] [ 0 ] = len ;
msg = theLines [ 0 ] ;
if ( user [ 0 ] && len < STRING_SIZE - 4 - user [ 0 ] ) {
AddPBuf ( msg , "\P (" ) ;
AddPBuf ( msg , user ) ;
AddPBuf ( msg , "\P)" ) ;
}
MoveTo ( leftMarg , ( numLines - 1 ) * lineHeight + topMarg ) ;
DrawString ( msg ) ;
for ( ix = 0 ; ix < numLines - 1 ; ix ++ ) {
theLines [ ix ] = theLines [ ix + 1 ] ;
}
theLines [ numLines - 1 ] = msg ;
// Notify the user that we received a message
Notification ( ) ;
}
// Handle the Ping message AppleEvent
//
pascal static OSErr
AEReceiveMessage ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
unsigned char s [ STRING_SIZE ] ;
unsigned char nm [ NAME_SIZE ] ;
short err ;
long type , size , nmSize ;
// Check for the text
err = AEGetParamPtr ( theEvent , pingSenderText , typeChar , ( void * ) & type ,
( void * ) & s [ 1 ] , STRING_SIZE , & size ) ;
// And the name...
if ( ! err ) {
err = AEGetParamPtr ( theEvent , pingSenderName , typeChar , ( void * ) & type ,
( void * ) & nm [ 1 ] , STRING_SIZE , & nmSize ) ;
nm [ 0 ] = nmSize ;
if ( err ) { // X Brand - No Name
nm [ 0 ] = 0 ;
err = 0 ;
}
}
if ( ! err ) {
s [ 0 ] = '-' ;
AddString ( s , size + 1 , nm ) ;
}
if ( err ) {
// Must interact to report error
if ( AEInteractWithUser ( 3600 , NULL , NULL ) ) {
DSErrCode = err ;
ExitToShell ( ) ;
}
Fatal ( err ) ;
} else { // Extract the destination from the received message
TargetID tid ;
unsigned long type ;
long siz ;
err = AEGetAttributePtr ( theEvent , keyAddressAttr , typeTargetID , & type ,
( void * ) & tid , sizeof ( tid ) , & siz ) ;
if ( ! err ) {
thePPCPort . name = tid . name ;
theLocation = tid . location ;
hasDest = 1 ;
lastTime = TickCount ( ) ; // New destination is valid
}
}
}
// Open Application - initialize
//
pascal static OSErr
AEOpenAppHandler ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
return noErr ;
}
// Quit the application
//
pascal static OSErr
AEQuitAppHandler ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
gRunning = 0 ;
return noErr ;
}
// We have no documents
//
pascal static OSErr
AEOpenDocHandler ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
return errAEEventNotHandled ;
}
// We have no documents
//
pascal static OSErr
AEPrintDocHandler ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
return errAEEventNotHandled ;
}
// We have no documents
//
pascal static OSErr
AEHandleReply ( AppleEvent * theEvent , AppleEvent * reply , long refCon )
{
return 0 ;
}
// Check for needed features - mainly, AppleEvents
//
static void
CheckMachine ( void )
{
long response = 0L ;
Str255 s ;
if ( Gestalt ( gestaltAppleEventsAttr , & response ) || ! ( response & 1 ) ) {
GetIndString ( s , errStrings , errNeedAppleEvents ) ;
ParamText ( s , NULL , NULL , NULL ) ;
Alert ( ALRTGeneralAlert , NULL ) ;
ExitToShell ( ) ;
}
}
// Initialize the application data
//
static void
InitApp ( void )
{
MenuHandle mh ;
Handle mBar ;
short ix ;
// Do we have an environment ?
CheckMachine ( ) ;
// Window
gWindow = GetNewWindow ( 128 , NULL , NULL ) ;
if ( ! gWindow ) {
Fatal ( QDError ( ) ) ;
}
SelectWindow ( gWindow ) ;
ShowWindow ( gWindow ) ;
SetPort ( gWindow ) ;
TextFont ( 1 ) ;
TextSize ( 10 ) ;
TextFace ( 0 ) ;
TextMode ( srcOr ) ;
// Set up font data
GetFontInfo ( & txInfo ) ;
lineHeight = txInfo . ascent + txInfo . descent + txInfo . leading ;
numLines = topPart / lineHeight ;
topMarg = ( topPart - lineHeight * numLines ) / 2 + txInfo . ascent ;
// Allocate buffers for storing incoming message data
theLines = ( unsigned char * * ) NewPtrClear ( sizeof ( unsigned char * ) * numLines ) ;
if ( ! theLines ) {
Fatal ( MemError ( ) ) ;
}
for ( ix = 0 ; ix < numLines ; ix ++ ) {
theLines [ ix ] = ( unsigned char * ) NewPtrClear ( STRING_SIZE ) ;
if ( ! theLines [ ix ] ) {
Fatal ( MemError ( ) ) ;
}
}
// Where do we input our text ?
textRect . top = 0 ;
textRect . bottom = ( bottomPart / lineHeight ) * lineHeight ;
textRect . left = 0 ;
textRect . right = lineWidth ;
OffsetRect ( & textRect , leftMarg , ( bottomPart - textRect . bottom ) / 2 + topPart + 1 ) ;
// Make input text edit
teH = TENew ( & textRect , & textRect ) ;
if ( ! teH ) {
Fatal ( MemError ( ) ) ;
}
// Install menus
mBar = GetNewMBar ( 128 ) ;
if ( ! mBar ) {
Fatal ( ResError ( ) ) ;
}
SetMenuBar ( mBar ) ;
DrawMenuBar ( ) ;
mh = GetMHandle ( 128 ) ;
if ( ! mh ) {
Fatal ( ResError ( ) ) ;
}
AddResMenu ( mh , 'DRVR' ) ;
// Install AppleEvent handlers
AEInstallEventHandler ( pingClass , pingMessage , AEReceiveMessage , 0L , FALSE ) ;
AEInstallEventHandler ( kCoreEventClass , kAEOpenApplication , AEOpenAppHandler , 0L , FALSE ) ;
AEInstallEventHandler ( kCoreEventClass , kAEQuitApplication , AEQuitAppHandler , 0L , FALSE ) ;
AEInstallEventHandler ( kCoreEventClass , kAEOpenDocuments , AEOpenDocHandler , 0L , FALSE ) ;
AEInstallEventHandler ( kCoreEventClass , kAEPrintDocuments , AEPrintDocHandler , 0L , FALSE ) ;
AEInstallEventHandler ( kCoreEventClass , kAEAnswer , AEHandleReply , 0L , FALSE ) ;
// A few utility things
aRgn = NewRgn ( ) ;
if ( ! aRgn ) {
Fatal ( MemError ( ) ) ;
}
Clear ( gNmRec ) ;
TEFeatureFlag ( teFOutlineHilite , TEBitSet , teH ) ;
GetUserName ( userName ) ;
}
// Draw the contents of our (only) window
//
static void
DrawWindow ( void )
{
short ix ;
PenNormal ( ) ;
PenPat ( qd . gray ) ;
MoveTo ( leftMarg , topPart ) ;
Line ( lineWidth , 0 ) ;
PenPat ( qd . black ) ;
EraseRect ( & textRect ) ;
TEUpdate ( & textRect , teH ) ;
// Loop through our stored strings and draw
for ( ix = 0 ; ix < numLines ; ix ++ ) {
MoveTo ( leftMarg , topMarg + ix * lineHeight ) ;
DrawString ( theLines [ ix ] ) ;
}
}
// Handle the Update Event in gEvent
//
static void
Update ( void )
{
WindowPtr wp = ( WindowPtr ) gEvent . message ;
SetPort ( wp ) ;
BeginUpdate ( wp ) ;
// Only draw contents if it's our window
if ( wp == gWindow ) {
DrawWindow ( ) ;
}
EndUpdate ( wp ) ;
}
// Handle Activate Event in gEvent
//
static void
Activate ( void )
{
if ( ( WindowPtr ) gEvent . message == gWindow ) {
if ( gEvent . modifiers & activeFlag ) {
TEActivate ( teH ) ;
} else {
TEDeactivate ( teH ) ;
}
}
}
// Handle mouseDown in our window
//
static void
ClickWindow ( void )
{
Point p = gEvent . where ;
SetPort ( gWindow ) ;
GlobalToLocal ( & p ) ;
if ( PtInRect ( p , & textRect ) ) {
TEClick ( p , gEvent . modifiers & shiftKey , teH ) ;
}
}
#define HEIGHT 5
// Our about box - nothing too fancy
// The Delays are not too "nice" but hey, it's an about box
//
static void
DoAbout ( void )
{
register short ix ;
register short wid ;
register short end ;
Str255 s ;
long l ;
Handle h ;
Rect r ;
register Rect * rr = & r ;
// Fill the window, slowly
SetPort ( gWindow ) ;
wid = gWindow -> portRect . right ;
end = gWindow -> portRect . bottom ;
rr -> top = 0 ;
rr -> bottom = HEIGHT ;
rr -> left = 0 ;
rr -> right = wid ;
for ( ix = 0 ; ix < end ; ix += HEIGHT ) {
PaintRect ( rr ) ;
Delay ( 1 , & l ) ;
rr -> top += HEIGHT ;
rr -> bottom += HEIGHT ;
}
TextMode ( srcXor ) ;
// Draw version info
h = GetResource ( 'vers' , 1 ) ;
if ( h ) {
BlockMove ( & ( * h ) [ 6 ] , s , ( * h ) [ 6 ] + 1 ) ; // Short Version
MoveTo ( gWindow -> portRect . right - StringWidth ( s ) - 5 ,
gWindow -> portRect . bottom - 5 ) ;
DrawString ( s ) ;
ReleaseResource ( h ) ;
}
// Draw our strings
Delay ( DELAY , & l ) ;
GetIndString ( s , 128 , 4 ) ;
ix = StringWidth ( s ) ;
MoveTo ( ( wid - ix ) / 2 , 30 ) ;
DrawString ( s ) ;
Delay ( DELAY , & l ) ;
GetIndString ( s , 128 , 5 ) ;
ix = StringWidth ( s ) ;
MoveTo ( ( wid - ix ) / 2 , 50 ) ;
DrawString ( s ) ;
// Wait for click
Delay ( DELAY , & l ) ;
while ( ! Button ( ) ) {
EventAvail ( keyDownMask | mDownMask , & gEvent ) ;
SystemTask ( ) ;
if ( gEvent . when > 600 + l ) {
break ;
}
}
// Restore environs
TextMode ( srcOr ) ;
rr -> top = 0 ;
rr -> bottom = HEIGHT ;
rr -> left = 0 ;
rr -> right = wid ;
for ( ix = 0 ; ix < end ; ix += HEIGHT ) {
EraseRect ( rr ) ;
Delay ( 1 , & l ) ;
rr -> top += HEIGHT ;
rr -> bottom += HEIGHT ;
}
InvalRect ( & gWindow -> portRect ) ;
}
// We need somewhere to send to
//
static void
DoSelectDestination ( void )
{
Str255 prompt , label , type ;
// Set up strings
GetIndString ( prompt , 128 , 1 ) ;
GetIndString ( label , 128 , 2 ) ;
GetIndString ( type , 128 , 3 ) ;
// Zero out return structs
Clear ( theLocation ) ;
Clear ( thePPCPort ) ;
// Get the application to talk to
hasDest = ! PPCBrowser ( prompt , label , FALSE , & theLocation , & thePPCPort ,
NULL , type ) ;
}
// Handle the edit menu
//
static void
EditMenu ( short item )
{
// Check for System Edit
if ( ! SystemEdit ( item - 1 ) ) {
switch ( item ) {
case 3 :
TECut ( teH ) ;
break ;
case 4 :
TECopy ( teH ) ;
break ;
case 5 :
TEPaste ( teH ) ;
break ;
case 6 :
TEDelete ( teH ) ;
break ;
// Select All
case 8 :
TESetSelect ( 0 , 32768 , teH ) ;
break ;
}
}
}
// Update Menus - dis-/enable edit menu items
//
static void
UpdateMenus ( void )
{
short ix ;
Boolean b = 0 ;
MenuHandle mh = GetMHandle ( 130 ) ;
short start = ( * teH ) -> selStart ;
short end = ( * teH ) -> selEnd ;
if ( ! mh ) {
Fatal ( MemError ( ) ) ;
}
// First, disable everything
for ( ix = 1 ; ix < 9 ; ix ++ ) {
DisableItem ( mh , ix ) ;
}
// For other windows, like DAs, we enable it
if ( FrontWindow ( ) != gWindow ) {
b = 1 ;
EnableItem ( mh , 1 ) ; // Undo as well
} else {
// Can always select all
EnableItem ( mh , 8 ) ;
// If selection, can copy & clear
if ( start != end ) {
b = 1 ;
}
}
{
long offset , len ;
// Check for paste
if ( 0 < ( len = GetScrap ( NULL , 'TEXT' , & offset ) ) ) {
EnableItem ( mh , 5 ) ;
}
}
// Maybe enable some items - but not Undo !
if ( b ) {
for ( ix = 3 ; ix < 7 ; ix ++ ) {
if ( ix != 5 ) { // Paste handled separately
EnableItem ( mh , ix ) ;
}
}
}
}
// Handle a menu selection
//
static void
DoMenu ( unsigned long cmd )
{
short menu = ( cmd >> 16 ) & 0x7fff ;
short item = cmd & 0x7fff ;
Str255 da ;
long now , then ;
if ( ! menu || ! item ) {
return ;
}
// Show selection
HiliteMenu ( menu ) ;
now = TickCount ( ) ;
switch ( menu ) {
case 128 : // Apple Menu
if ( item == 1 ) {
DoAbout ( ) ;
} else {
GetItem ( GetMHandle ( 128 ) , item , da ) ;
OpenDeskAcc ( da ) ;
}
break ;
case 129 : // File Menu
if ( item == 1 ) {
DoSelectDestination ( ) ;
} else {
gRunning = 0 ;
}
break ;
case 130 : // Edit Menu
EditMenu ( item ) ;
break ;
}
// See to it we flash for at least 8 ticks
then = TickCount ( ) ;
if ( then - now < 8L ) {
Delay ( 8L - ( then - now ) , & then ) ;
}
HiliteMenu ( 0 ) ;
}
// Handle mouseDown in gEvent
//
static void
Click ( void )
{
WindowPtr w ;
short code , delta ;
unsigned long pos , size ;
Rect limit ;
code = FindWindow ( gEvent . where , & w ) ;
switch ( code ) {
case inGrow : // Resize window - only horizontally
limit = w -> portRect ;
limit . left = MIN_WID_PIXELS ;
limit . right = ( * GetGrayRgn ( ) ) -> rgnBBox . right - RIGHT_STRIP ;
if ( limit . right < MIN_WID_PIXELS ) {
limit . right = MIN_WID_PIXELS ;
}
if ( limit . right > MAX_WID_PIXELS ) {
limit . right = MAX_WID_PIXELS ;
}
limit . bottom ++ ;
limit . top = limit . bottom ;
size = GrowWindow ( w , gEvent . where , & limit ) ;
if ( size ) {
SizeWindow ( w , size & 0xFFFF , size >> 16 , TRUE ) ;
delta = lineWidth ;
lineWidth = w -> portRect . right - 2 * leftMarg;
delta = lineWidth - delta ;
( * teH ) -> viewRect . right += delta ;
( * teH ) -> destRect . right += delta ;
textRect . right += delta ;
TECalText ( teH ) ;
limit = w -> portRect ;
limit . top = topPart ;
InvalRect ( & limit ) ;
EraseRect ( & limit ) ;
}
break ;
case inContent : // Select text ?
if ( FrontWindow ( ) != w ) {
SelectWindow ( w ) ;
} else if ( w == gWindow ) {
ClickWindow ( ) ;
}
break ;
case inDrag : // Move window
limit = ( * GetGrayRgn ( ) ) -> rgnBBox ;
DragWindow ( w , gEvent . where , & limit ) ;
break ;
case inMenuBar : // Select item
UpdateMenus ( ) ; // Make sure menus are in OK state
pos = MenuSelect ( gEvent . where ) ;
if ( pos ) {
DoMenu ( pos ) ;
}
break ;
case inSysWindow : // DA handling - not really necessary under 7.0...
SystemClick ( & gEvent , w ) ;
break ;
}
}
// Handle suspend/resume event - we don't get mouseMoved since we pass
// NULL to WaitNextEvent
//
static void
OsEvent ( void )
{
if ( ( unsigned long ) gEvent . message >> 24 == 1 ) {
isIn = gEvent . message & 1 ;
SetPort ( gWindow ) ;
if ( isIn ) {
if ( gEvent . message & 2 ) { // Convert Scrap
TEFromScrap ( ) ; // Not really necessary because we're >= 4.1...
}
// Activate windows
TEActivate ( teH ) ;
// The user responds...
if ( gNmRec . nmIcon ) {
// If we're in, we don't need the flashing icon anymore...
NMRemove ( & gNmRec ) ;
Clear ( gNmRec ) ;
}
InitCursor ( ) ; // Since we use no mouse region, we have to
} else {
if ( gEvent . message & 2 ) { // Convert Scrap
TEToScrap ( ) ;
}
// Deactivate windows
TEDeactivate ( teH ) ;
}
}
}
// Handle HLE - only AppleEvents, I hope
//
static void
HighLevelEvent ( void )
{
short err = AEProcessAppleEvent ( & gEvent ) ;
if ( err ) { // Some people say "Don't check return code from AEProcessAppleEvent."
// I don't. Say, that is.
Fatal ( err ) ;
}
}
// Sending because we pressed enter or return
//
static void
DoSend ( void )
{
AppleEvent evt = { 0 , 0 } ;
AEAddressDesc adsc = { 0 , 0 } ;
Handle h ;
TargetID tid ;
short err ;
// Check if address has expired
// Expires after 20 seconds
if ( hasDest && ( lastTime < TickCount ( ) - 60 * 20 ) ) {
if ( 1 == Alert ( 130 , NULL ) ) {
hasDest = 0 ;
}
}
lastTime = TickCount ( ) ;
// Check whether we have anything to send to
if ( ! hasDest ) {
DoSelectDestination ( ) ;
}
h = ( Handle ) TEGetText ( teH ) ;
if ( ! hasDest || ! h ) {
SysBeep ( 30 ) ;
return ;
}
// Set up the target record we need as destination
tid . sessionID = 0 ;
tid . name = thePPCPort . name ;
tid . location = theLocation ;
tid . recvrName = thePPCPort . name ;
err = AECreateDesc ( typeTargetID , ( void * ) & tid , sizeof ( tid ) , & adsc ) ;
if ( ! err ) {
// Make event
err = AECreateAppleEvent ( pingClass , pingMessage , & adsc , kAutoGenerateReturnID ,
kAnyTransactionID , & evt ) ;
}
// On track; add data
if ( ! err ) {
// Add our text
HLock ( h ) ;
AddString ( ( unsigned char * ) * h , ( * teH ) -> teLength , userName ) ;
err = AEPutParamPtr ( & evt , pingSenderText , typeChar , * h , ( * teH ) -> teLength ) ;
HUnlock ( h ) ;
// Clear the text
TESetText ( NULL , 0L , teH ) ;
EraseRect ( & textRect ) ;
TEUpdate ( & textRect , teH ) ;
}
if ( ! err && userName [ 0 ] ) {
err = AEPutParamPtr ( & evt , pingSenderName , typeChar , ( void * ) & userName [ 1 ] ,
userName [ 0 ] ) ;
}
// Time for communicating
if ( ! err ) {
// Send the event
err = AESend ( & evt , NULL , kAEQueueReply | kAEAlwaysInteract | kAECanSwitchLayer ,
kAENormalPriority , kAEDefaultTimeout , NULL , NULL ) ;
}
// Dispose descs
if ( evt . dataHandle ) {
AEDisposeDesc ( & evt ) ;
}
if ( adsc . dataHandle ) {
AEDisposeDesc ( & adsc ) ;
}
if ( err ) {
Fatal ( err ) ;
}
}
// Handle keyDown event
//
static void
Type ( void )
{
long cmd ;
// Set a known port
SetPort ( gWindow ) ;
if ( gEvent . modifiers & cmdKey ) {
UpdateMenus ( ) ; // Make sure menus are in OK state
cmd = MenuKey ( gEvent . message & 0xff ) ;
if ( cmd ) {
DoMenu ( cmd ) ;
} else {
//• Should add word move here
}
} else {
switch ( ( gEvent . message >> 8 ) & 0xff ) {
case 0x24 : // Return
case 0x4c : // Enter - new KB
case 0x34 : // Enter - old KB and PowerBooks
DoSend ( ) ;
break ;
default :
TEKey ( gEvent . message & 0xff , teH ) ; // TEKey handles arrow keys on charcode...
break ;
}
}
}
// Handle the event in gEvent
//
static void
HandleEvent ( void )
{
switch ( gEvent . what ) {
case updateEvt : // Redraw window
Update ( ) ;
break ;
case activateEvt : // Handle text highlight
Activate ( ) ;
break ;
case mouseDown : // User Clicked
Click ( ) ;
break ;
case keyDown :
case autoKey : // Type, or command key
Type ( ) ;
break ;
case diskEvt : // Format disk, just for kicks
if ( gEvent . message & 0xffff0000 != 0L ) {
Point p = { 110 , 130 } ;
( void ) DIBadMount ( p , gEvent . message ) ;
}
break ;
case osEvt : // Switch in/out
OsEvent ( ) ;
break ;
case kHighLevelEvent : // AppleEvent - with message ?
HighLevelEvent ( ) ;
break ;
}
// No operation should allow the text to become too large
if ( GetHandleSize ( ( Handle ) TEGetText ( teH ) ) >= STRING_SIZE - 1 ) {
SysBeep ( 20 ) ;
TESetSelect ( STRING_SIZE - 2 , GetHandleSize ( ( Handle ) TEGetText ( teH ) ) , teH ) ;
TEDelete ( teH ) ;
// Delete spurious commands in the event queue...
FlushEvents ( keyDownMask | autoKeyMask | mDownMask , 0 ) ;
}
}
// Main - event loop
//
void
main ( void )
{
InitMac ( ) ;
InitApp ( ) ;
InitCursor ( ) ; // Don't want a watch, which is what the Finder leaves us
while ( gRunning ) {
// In the background, we sleep for a long time. In the foreground,
// we need to flash a caret, thus we use GetCaretTime.
// Under 6.0 UniFinder, device drivers lock up if we pass a long value
// to WaitNextEvent. However, if they graft AppleEvents onto 6.0, they
// will probably fix that one too...
if ( WaitNextEvent ( -1 , & gEvent , isIn ? GetCaretTime ( ) : 0x7fff , NULL ) ) {
HandleEvent ( ) ;
}
if ( isIn && FrontWindow ( ) == gWindow ) {
// Only flash caret while in the foreground
TEIdle ( teH ) ;
}
}
}